The first step is to analyze if the icon set being packed can be integrated into Trilium.
Trilium only supports font-based icon sets, with the following formats:
| Extension | MIME type | Description |
|---|---|---|
.woff2
|
font/woff2
|
Recommended due to great compression (low size). |
.woff
|
font/woff
|
Higher compatibility, but the font file is bigger. |
.ttf
|
font/ttf
|
Most common, but highest font size. |
Trilium does not support the following formats:
.eot fonts (legacy and proprietary).In this case, the font must be manually converted to one of the supported
formats (ideally .woff2).
In order to create a new icon pack from a set of icons, it must meet the following criteria:
.css file that can be used to
extract the icon names from.As an example throughout this page, we are going to go through the steps of integrating Phosphor Icons.
This is the most difficult part of creating an icon pack, since it requires processing of the icon list to match Trilium's format.
The icon pack manifest is a JSON file with the following structure:
{
"icons": {
"bx-ball": {
"glyph": "\ue9c2",
"terms": [ "ball" ]
},
"bxs-party": {
"glyph": "\uec92"
"terms": [ "party" ]
}
}
}
bx-ball),
to its corresponding code point in the font (\ue9c2)
and the terms/aliases used for search purposes.In order to generate this manifest, generally a script is needed that
processes an already existing list. In the case of Phosphor Icons, the
icon list comes in a file called selection.json with
the following format:
{
"icons": [
{
"icon": {
"paths": [ /* [...] */ ],
"grid": 0,
"attrs": [{}],
"isMulticolor": false,
"isMulticolor2": false,
"tags": ["acorn"]
},
"attrs": [{}],
"properties": {
"id": 0,
"order": 1513,
"name": "acorn",
"code": 60314,
"ligatures": "acorn",
"prevSize": 16
},
"setIdx": 0,
"setId": 0,
"iconIdx": 0
},
/* [...] */
]
}
As such, we can write a Node.js script to automatically process the manifest file:
import { join } from "node:path";
import { readFileSync } from "node:fs";
function processIconPack(packName) {
const path = join(packName);
const selectionMeta = JSON.parse(readFileSync(join(path, "selection.json"), "utf-8"));
const icons = {};
for (const icon of selectionMeta.icons) {
let name = icon.properties.name;
if (name.endsWith(`-${packName}`)) {
name = name.split("-").slice(0, -1).join("-");
}
const id = `ph-${name}`;
icons[id] = {
glyph: `${String.fromCharCode(icon.properties.code)}`,
terms: [ name ]
};
}
return JSON.stringify({
icons
}, null, 2);
}
console.log(processIconPack("light"));
.woff2, .woff,
.ttf) format.
font/woff2).role appears as file,
otherwise the font will not be identified..woff2,
.woff, .ttf. As such, there's not
much reason to upload more than one font per icon pack.Before an icon pack can be used, it needs to have a prefix defined. This prefix uniquely identifies the icon pack so that it can be used throughout the application.
To do so, Trilium makes use of the same format that was used for the internal
icon pack (Boxicons). For example, when an icon from Boxicons is set, it
looks like this: #iconClass="bx bxs-sushi".
In this case, the icon pack prefix is bx and
the icon class name is bxs-sushi.
In order for an icon pack to be recognized, the prefix must be specified
in the #iconPack label.
For our example with Phosphor Icons, we can use the ph prefix
since it also matches the prefix set in the original CSS. So in this case
it would be #iconPack=ph.
If the icon pack doesn't show up, look through the Backend (server) logs for clues.
ERROR: Icon pack is missing WOFF/WOFF2/TTF attachment: Boxicons v3 400 (dup) (XRzqDQ67fHEK).